#[macro_use] extern crate rocket;

use rocket::serde::{Serialize, json::Json};

use rocket_db_pools::{Database, Connection};
use rocket_db_pools::sqlx::{self}; 

use futures::{ future::TryFutureExt, stream::TryStreamExt};

#[derive(Database)]
#[database("mysql_db")]
struct Logs(sqlx::MySqlPool);

type Result<T, E = rocket::response::Debug<sqlx::Error>> = std::result::Result<T, E>;

#[derive(Serialize)]
#[serde(crate = "rocket::serde")]
struct FUser {
    f_id:Option<i32>,
    f_username: Option<String>,
    f_realname: Option<String>,
    f_uuid:Option<String>
}

#[get("/<id>")]
async fn read(mut db: Connection<Logs>, id: i64) -> Option<Json<FUser>> {
    sqlx::query!("SELECT f_id,f_username,f_realname,f_uuid FROM tb_user WHERE f_id = ?",id)
        .fetch_one(&mut **db)
        .map_ok(|r| Json(FUser { f_id: Some(r.f_id), f_username: r.f_username, f_realname: r.f_realname, f_uuid: r.f_uuid }))
        .await 
        .ok()
}

#[get("/all")]
async fn read_all(mut db: Connection<Logs>) -> Result<Json<Vec<FUser>>> {
    let users = sqlx::query!("SELECT f_id,f_username,f_realname,f_uuid FROM tb_user")
        .fetch(&mut **db)
        .map_ok(|r| FUser{f_id: Some(r.f_id), f_username: r.f_username, f_realname: r.f_realname, f_uuid: r.f_uuid})
        .try_collect::<Vec<_>>()
        .await?;
        Ok(Json(users))
}

#[launch]
fn rocket() -> _ {
   rocket::build()
   .attach(Logs::init())
   .mount("/", routes![read,read_all]) 
}